#!/usr/bin/env python

import struct
import os.path
import sys
import pygtk
pygtk.require('2.0')
import gobject, gtk
import numpy

from PIL import Image

from config import Config
from wordnet_processor import Wordnet_Voter

class Image_Viewer:
    def __init__(self):
        self.__init_main_window()
        
        self.images = open(Config['IMAGES'], 'rb')
        self.metadata = open(Config['METADATA'],'rb')
        
        self.images.seek(0, 2)
        self.n_images = self.images.tell() / Config['IMGSIZE']
        self.images.seek(0)
        
        self.index = 0
        self.update_gui()
        return


    def __init_main_window(self):
        # create a new window
        window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        window.connect("destroy", self.destroy)
        window.set_default_size(400, 100)
        window.set_title("Tiny Images Viewer")
        window.connect("key_press_event", self.on_key_press_event)
        
        
        accel_group = gtk.AccelGroup()
        window.add_accel_group(accel_group)
        
        # main menu
        quit_item = gtk.MenuItem("Quit")
        quit_item.connect("activate", self.destroy, 'file.quit')        
        quit_item.add_accelerator("activate", accel_group, ord('q'), gtk.gdk.CONTROL_MASK, gtk.ACCEL_VISIBLE)
        quit_item.show()

        file_menu = gtk.Menu()
        file_menu.append(quit_item)

        root_menu = gtk.MenuItem("File")
        root_menu.set_submenu(file_menu)
        root_menu.show()

        menu_bar = gtk.MenuBar()
        menu_bar.append(root_menu)
        menu_bar.show()
        
        # keyword entry
        self.keyword_entry = gtk.Entry()
        self.keyword_entry.connect("activate", self.on_text_event, 'entry.set_text')
        self.keyword_entry.show()
        
        # index entry
        self.index_entry = gtk.Entry()
        self.index_entry.connect("activate", self.on_text_event, 'entry.set_text')
        self.index_entry.show()
        
        # image
        self.image = gtk.Image()
        self.image.show()
        
        # status bar
        self.status_bar = gtk.Statusbar();
        self.status_bar.show()
        
        # rows, columns, homogeneous
        table = gtk.Table(2, 2, False)
        table.attach(self.keyword_entry, 0, 1, 0, 1)
        table.attach(self.index_entry, 1, 2, 0, 1)
        table.attach(self.image, 0, 2, 1, 2)
        table.show()
        
        # vbox
        vbox = gtk.VBox(False, 0)
        vbox.pack_start(menu_bar, False, False, 0)        
        vbox.pack_start(table, False, False, 0)
        vbox.pack_start(self.status_bar, False, False, 0)
        vbox.show() 
        
        window.add(vbox)
        window.show()
    
    
    def destroy(self, widget, data=None):
        gtk.main_quit()   
        
        
    def update_gui(self):
        self.index_entry.set_text('%d' % (self.index))
        self.keyword_entry.set_text(self.get_keyword_from_index(self.index))
        
        numpy_img = self.get_tiny_image_from_index(self.index)
        pixbuf = gtk.gdk.pixbuf_new_from_array(numpy_img, gtk.gdk.COLORSPACE_RGB, 8)            
        pixbuf = pixbuf.scale_simple(320, 320, gtk.gdk.INTERP_BILINEAR)        
        self.image.set_from_pixbuf(pixbuf)
        return


    def on_text_event(self, widget, event):
        if widget == self.keyword_entry:
            keyword = self.keyword_entry.get_text()
            tmp = self.get_index_from_keyword(keyword)
            if tmp is not None:
                self.index = tmp
        elif widget == self.index_entry:
            self.index = int(self.index_entry.get_text())
        self.update_gui()
        return
    
    
    def on_key_press_event(self, widget, event):
        keyname = gtk.gdk.keyval_name(event.keyval)
        if keyname == 'Up'and self.index < self.n_images:
            self.index += 1
            self.update_gui()
        elif keyname == 'Down' and self.index > 0:
            self.index -= 1
            self.update_gui()
        return
    
    
    def get_tiny_image_from_index(self, index):
        size = Config['IMGSIZE']
        
        self.images.seek(size * index)
        img = numpy.fromfile(self.images, dtype=numpy.uint8, count=Config['IMGSIZE']).reshape((3, 32, 32))
        red, green, blue = img[0], img[1], img[2]
        img = numpy.dstack((red, green, blue)).reshape((32, 32, 3)) 
        return numpy.rot90(img, 3)                   
    
    
    def get_keyword_from_index(self, index):
        size = Config['METADATASIZE']
        
        self.metadata.seek(size * index)
        keyword = struct.unpack_from('>80s', self.metadata.read(size))
        return keyword[0].strip()
    
    
    def get_index_from_keyword(self, keyword):
        self.metadata.seek(0, 2)
        self.n_keywords = self.metadata.tell() / Config['METADATASIZE']
        self.metadata.seek(0)

        n = 0
        lower_bound = 0
        upper_bound = self.n_keywords
        while n < 64:
            n += 1
            index = (lower_bound + upper_bound) / 2
            k = self.get_keyword_from_index(index)
            print keyword, lower_bound, upper_bound, k
            
            if k > keyword:
                upper_bound = index
            elif k < keyword:
                lower_bound = index
            else:
                return index
        return
         
        
if __name__ == "__main__":
    Image_Viewer()
    gtk.gdk.threads_init()
    gtk.main()
